﻿using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.Windsor;

namespace User.Web.UI.Helper.CastleWindsor
{
    /// <summary>
    /// Unsere eigene Klasse zum Erstellen der passenden Controller, damit wir hier auch direkt Parameter an die Kontroller
    /// per Di übergeben können, denn normale Kontroller haben nur einen Default Konstruktor.
    /// </summary>
    public class CustomControllerFactory : DefaultControllerFactory
    {
        private readonly IWindsorContainer _container;
        private const string CurrentControllerIndexName = "CurrentControllerItem";

        /// <summary>
        /// Den Windsor Container für unser Projekt übergeben
        /// </summary>
        /// <param name="container">Unser aktueller Windsor Kontainer</param>
        public CustomControllerFactory(IWindsorContainer container)
        {
            if (container == null)
            {
                throw new NullReferenceException("IWindsorContainer is Null");
            }

            _container = container;
        }

        /// <summary>
        /// Erstellen der passenden Controller Instanzen anhand unseres Containers werden die Instanzen automatisch aufgelöst.
        /// </summary>
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
            }

            //Unseren Controller auflösen per Castle Windsor
            var controller = (IController)this._container.Resolve(controllerType);

            //Prüfen ob bereits ein Controller im HttpContext enthalten ist, wenn ja wird dieser entfernt um den aktuellen Hinzufügen zu können.
            if(HttpContext.Current.Items.Contains(CurrentControllerIndexName))
            {
                HttpContext.Current.Items.Remove(CurrentControllerIndexName);
            }

            //Unseren aktuellen Controller dem Context hinzufügen, dann können wir später darauf zugreifen.
            HttpContext.Current.Items.Add(CurrentControllerIndexName, controller);
            
            return controller;
        }

        /// <summary>
        /// Gibt den aktuellen Controller zurück der aktuell verwendet wird.
        /// </summary>
        public static IController GetCurrentController()
        {
            //Prüfen ob ein Controller im aktuellen Context hinterlegt wurde.
            if(HttpContext.Current.Items.Contains(CurrentControllerIndexName))
            {
                return (IController) HttpContext.Current.Items[CurrentControllerIndexName];
            }

            throw  new Exception("No Controller found in the Current HttpContext");
        }

        public override void ReleaseController(IController controller)
        {
            //Wenn der Controller "aufgelöst werden soll, dann auch den Controller aus dem Context entfernen.
            if (HttpContext.Current.Items.Contains(CurrentControllerIndexName))
            {
                HttpContext.Current.Items.Remove(CurrentControllerIndexName);
            }

            this._container.Release(controller);
        }
    }
}